/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */


package Utilities;

import Exception.KwickKioskServiceException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.SecretKeySpec;

/**
 * this class encrypts and decrypts the string data. it can be password or credit card data
 * @author tejinder
 */
public class CryptUtilities {

    private static Logger log =  Logger.getLogger(CryptUtilities.class.getName());

    /**
     * Hashes a string. Converts a user-entered pass phrase into a hashed binary value which is
     * used as the encryption key.
     * @param theString the String to crypt
     */
    public static String crypt(String data) throws KwickKioskServiceException {
        
        String toEncrypt =  data;
        String encryptedStr = "";
        byte[] encryptedBytes =  null;
        byte[] messageBytes =  toEncrypt.getBytes();

        //shared secret
        byte[] messageKeyBytes = new byte[] {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
        
        String sPadding = "ISO10126Padding"; //"ISO10126Padding", "PKCS5Padding"

        try {
            encryptedBytes = encrypt(messageKeyBytes, sPadding, messageBytes);
        } catch (Exception ex) {
            log.log(Level.SEVERE, null, ex);
            throw new KwickKioskServiceException("CryptUtilities : crypt", ex.getMessage());

        }

         encryptedStr =new String(SimpleBase64Encoder.encode(encryptedBytes));

         return encryptedStr;

    }

    /**
     * this method encrypts the data
     * @param keyBytes
     * @param sPadding
     * @param messageBytes
     * @return
     * @throws Exception
     */
    private static byte[] encrypt(byte[] keyBytes, String sPadding, byte[] messageBytes) throws Exception {
        Cipher cipher = getAESECBEncryptor(keyBytes, sPadding);
        return encrypt(cipher, messageBytes);
    }

    /**
     * this method uses built in algorithm provided by java
     * @param keyBytes
     * @param padding
     * @return
     * @throws Exception
     */
     private static Cipher getAESECBEncryptor(byte[] keyBytes, String padding) throws Exception{
        SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/"+padding);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        return cipher;
    }

     /**
      * encryption
      * @param cipher
      * @param dataBytes
      * @return
      * @throws Exception
      */
    private static byte[] encrypt(Cipher cipher, byte[] dataBytes) throws Exception{
        ByteArrayInputStream bIn = new ByteArrayInputStream(dataBytes);
        CipherInputStream cIn = new CipherInputStream(bIn, cipher);
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        int ch;
        while ((ch = cIn.read()) >= 0) {
          bOut.write(ch);
        }
        return bOut.toByteArray();
    }

    /**
     * this method decrypts the data beck to original data
     * @param data
     * @return
     */
    public static String decrypt(byte[] data) throws KwickKioskServiceException{

        byte[] toDecrypt =  data;

        String decryptedStr = "";

        //shared secret
        byte[] messageKeyBytes = new byte[] {  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
                0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

         String sPadding = "ISO10126Padding"; //"ISO10126Padding", "PKCS5Padding"
         byte[] decryptedBytes = null;

        try {
            decryptedBytes = decrypt(messageKeyBytes, sPadding, toDecrypt);
        } catch (Exception ex) {
           log.log(Level.SEVERE, null, ex);
           throw new KwickKioskServiceException("CryptUtilities : decrypt", ex.getMessage());
        }

        decryptedStr =  new String(decryptedBytes);

        return decryptedStr;
        
    }

    /**
     * uses decryption algorithm provided by java
     * @param keyBytes
     * @param sPadding
     * @param encryptedMessageBytes
     * @return
     * @throws Exception
     */
    private static byte[] decrypt(byte[] keyBytes, String sPadding, byte[] encryptedMessageBytes) throws Exception {
        Cipher decipher = getAESECBDecryptor(keyBytes, sPadding);
        return decrypt(decipher, encryptedMessageBytes);
    }

    /**
     * @param keyBytes
     * @param padding
     * @return
     * @throws Exception
     */
     private static Cipher getAESECBDecryptor(byte[] keyBytes, String padding) throws Exception{
        SecretKeySpec key = new SecretKeySpec(keyBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/"+padding);
        cipher.init(Cipher.DECRYPT_MODE, key);
        return cipher;
    }

     /**
      * decryption
      * @param cipher
      * @param dataBytes
      * @return
      * @throws Exception
      */
      private static byte[] decrypt(Cipher cipher, byte[] dataBytes) throws Exception{
        ByteArrayOutputStream bOut = new ByteArrayOutputStream();
        CipherOutputStream cOut = new CipherOutputStream(bOut, cipher);
        cOut.write(dataBytes);
        cOut.close();
        return bOut.toByteArray();
    }

}
